﻿#region Copyright(c) 2006 ZO, All right reserved.
// -----------------------------------------------------------------------------
// Copyright(c) 2006 ZO, All right reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//   1.  Redistribution of source code must retain the above copyright notice,
//       this list of conditions and the following disclaimer.
//   2.  Redistribution in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//   3.  The name of the author may not be used to endorse or promote products
//       derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// -----------------------------------------------------------------------------
#endregion


#region Using directives

using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics.CodeAnalysis;
using ZO.SmartCore.Core;

#endregion

namespace ZO.SmartCore.Xml
{
    /// <summary>
    /// represent the coolection of nodes in the XML Structure
    /// </summary>
    [SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix")]
    public class NodeList : DisposableObject, IEnumerable<Node>
    {

        #region Constructors
        /// <summary>
        /// Initializes a new instance of the <see cref="NodeList"/> class.
        /// </summary>
        /// <param name="parent">The parent.</param>
        protected internal NodeList(Node parent)
        {
            this._Parent = parent;
        }

        /// <summary>Gets the parent of this node (for nodes that can have parents).</summary>
        /// <returns>The Node that is the parent of the current node. If a node has just been created and not yet added to the tree, or if it has been removed from the tree, the parent is null. For all other nodes, the value returned depends on the <see cref="P:System.Xml.XmlNode.NodeType"></see> of the node. The following table describes the possible return values for the ParentNode property.NodeType Return Value of ParentNode Attribute, Document, DocumentFragment, Entity, Notation Returns null; these nodes do not have parents. CDATA Returns the element or entity reference containing the CDATA section. Comment Returns the element, entity reference, document type, or document containing the comment. DocumentType Returns the document node. Element Returns the parent node of the element. If the element is the root node in the tree, the parent is the document node. EntityReference Returns the element, attribute, or entity reference containing the entity reference. ProcessingInstruction Returns the document, element, document type, or entity reference containing the processing instruction. Text Returns the parent element, attribute, or entity reference containing the text node. </returns>
        protected internal virtual Node Parent
        {
            get
            {
                return _Parent;
            }
        }

        #endregion

        #region Destructor

        #endregion

        #region Fields
        private Node _Parent;
        private Collection<Node> _InternalChildNodes = new Collection<Node>();

        #endregion

        #region Events

        #endregion

        #region Operators

        #endregion

        #region Properties

        /// <summary>
        /// Gets an Dictionary containing the list of attributes for this node. 
        /// </summary>
        /// <remarks>Do Not</remarks>
        private Collection<Node> InternalChildNodes
        {
            get
            {
                return this._InternalChildNodes;
            } // get
        }

        /// <summary>
        /// Gets or sets the value with the specified key.
        /// </summary>
        /// <value></value>
        public Node this[int index]
        {
            get
            {

                return this.InternalChildNodes[index];
            }
            set
            {
                this.InternalChildNodes[index] = value;
            }
        }


        /// <summary>
        /// Gets the number of elements contained in the collection.
        /// </summary>
        /// <value></value>
        /// <returns>The number of elements contained in the collection.</returns>
        public int Count
        {
            get { return this.InternalChildNodes.Count; }
        }

        #endregion

        #region Methods

        /// <summary>
        /// Override This Method To Dispose Unmanaged Resources.
        /// </summary>
        protected override void DisposeManagedResources()
        {
            base.DisposeManagedResources();
            this._InternalChildNodes.Clear();
            this._Parent = null;
        }

        /// <summary>
        /// Adds an object to the end of the Collection. 
        /// </summary>
        /// <param name="item">The object to be added to the end of the Collection. The value can be a null reference (Nothing in Visual Basic) for reference types.</param>
        protected internal virtual void Add(Node item)
        {
            if (item == null)
            {
                return;
            }
            item.Parent = this.Parent;
            this.InternalChildNodes.Add(item);

            //if (item.NodeType == NodeType.Attribute)
            //{
            //    if (this.Parent.NodeType == NodeType.Element)
            //    {
            //        Attribute attr = (Attribute)item;
            //        ((Element)this.Parent).Attributes.Add(attr);
            //        return;
            //    }
            //    return;
            //}
            //else if (item.NodeType == NodeType.Text)
            //{
            //    if ((this.Parent.NodeType == NodeType.Element) || (this.Parent.NodeType == NodeType.Attribute) || (this.Parent.NodeType == NodeType.Comment))
            //    {
            //        item.Parent = this.Parent;
            //        this.InternalChildNodes.Add(item);
            //        return;
            //    }
            //    else
            //    {
            //        this.Parent.Value = item.Value;
            //    }

            //    return;
            //}
            //else if (item.NodeType == NodeType.Document)
            //{
            //    return;
            //}
            //else
            //{
            //    item.Parent = this.Parent;
            //    this.InternalChildNodes.Add(item);
            //    return;
            //}
        }

        /// <summary>
        /// Removes the first occurrence of a specific object from the Collection.
        /// </summary>
        /// <param name="item">The object to remove from the Collection. The value can be a null reference (Nothing in Visual Basic) for reference types.</param>
        public void Remove(Node item)
        {
            if (this.InternalChildNodes.Contains(item))
            {
                this.InternalChildNodes.Remove(item);
            }
        }

        /// <summary>
        /// Removes the element at the specified index of the Collection. 
        /// </summary>
        /// <param name="index">The zero-based index of the element to remove.</param>
        public void RemoveAt(int index)
        {
            this.InternalChildNodes.RemoveAt(index);
        }


        /// <summary>
        /// Determines whether an element is in the Collection. 
        /// </summary>
        /// <param name="item">The object to locate in the Collection. The value can be a null reference (Nothing in Visual Basic) for reference types.</param>
        /// <returns>
        /// 	true if item is found in the Collection; otherwise, false. 
        /// </returns>
        public bool Contains(Node item)
        {
            if (InternalChildNodes.Contains(item))
            {
                return true; 
            }

            return false;
        }

        /// <summary>
        /// Searches for the specified object and returns the zero-based index of the first occurrence within the entire Collection. 
        /// </summary>
        /// <param name="item">The object to locate in the List. The value can be a null reference (Nothing in Visual Basic) for reference types.</param>
        /// <returns>The zero-based index of the first occurrence of item within the entire Collection, if found; otherwise, -1. </returns>
        public int IndexOf(Node item)
        {
            return this.InternalChildNodes.IndexOf(item);
        }

        /// <summary>
        /// Inserts an element into the Collection at the specified index. 
        /// </summary>
        /// <param name="index">The zero-based index at which item should be inserted.</param>
        /// <param name="item">The object to insert. The value can be a null reference (Nothing in Visual Basic) for reference types.</param>
        public void Insert(int index, Node item)
        {
            this.InternalChildNodes.Insert(index, item);
        }

        /// <summary>
        /// Removes all elements from the Collection. 
        /// </summary>
        /// <exception cref="System.NotSupportedException">The collection is read-only. </exception>
        public void Clear()
        {
            this.InternalChildNodes.Clear();
        }


        /// <summary>
        /// Copies the entire Collection to a compatible one-dimensional Array, starting at the specified index of the target array. 
        /// </summary>
        /// <param name="array">The one-dimensional Array that is the destination of the elements copied from Collection. The Array must have zero-based indexing.</param>
        /// <param name="index">The zero-based index in array at which copying begins.</param>
        public void CopyTo(Node[] array, int index)
        {
            this.InternalChildNodes.CopyTo(array, index);
        }

        #endregion

        #region IEnumerable Members

        /// <summary>
        /// Returns an enumerator that iterates through the collection.
        /// </summary>
        /// <returns>
        /// A <see cref="T:System.Collections.Generic.IEnumerator`1"></see> that can be used to iterate through the collection.
        /// </returns>
        public IEnumerator<Node> GetEnumerator()
        {
            return this.InternalChildNodes.GetEnumerator();
        }

        /// <summary>
        /// Returns an enumerator that iterates through a collection.
        /// </summary>
        /// <returns>
        /// An <see cref="T:System.Collections.IEnumerator"></see> object that can be used to iterate through the collection.
        /// </returns>
        IEnumerator IEnumerable.GetEnumerator()
        {
            return this.InternalChildNodes.GetEnumerator();
        }

        #endregion

    }
}
